package com.woniuxy.three.pms.util;
/**
 * 
 * @ProjectName:Pms
 * @Date:2019年6月22日
 * @ClassName:CacheUtil.java
 * @Author: Capiudor
 * @Description:TODO 缓存工具
 * @Version:1.0
 * @See：参考版本
 *
 */

import java.time.Duration;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

@Component
public class CacheUtil {
	
	@Resource
	private StringRedisTemplate stringRedisTemplate;
	
	/***
	 * 设置缓存 并设置过期时间
	 * @param key
	 * @param value
	 * @param timeout  jdk 8 的引入的日期，在Springboot中的Redis使用此方法控制超时
	 */
	public void cacheWithTimeOut(String key,Object value,Duration timeout) {
		stringRedisTemplate.opsForValue().set(key, String.valueOf(value), timeout);
	}
	/**
	 * 设置缓存键值对、如果已经有这个Key、则覆盖这个键值对
	 * @param key
	 * @param value
	 */
	public void cacheWithKeyValue(String key,Object value) {
		stringRedisTemplate.opsForValue().set(key, String.valueOf(value));
	}
	
	/***
	 * 根据key获取值
	 * @param key
	 * @return
	 */
	public String getValueWithKey(String key) {
		Object object = stringRedisTemplate.opsForValue().get(key);
		if (object==null){
			return null;
		}
		return object.toString();
	}
	/**
	 * @Method cacheIncrement
	 * @Author Capiudor
	 * @Version  1.0
	 * @Description  设置过期时间的键值对 的自增长
	 * @Param:
	 * @Return void
	 * @Exception
	 * @Date 2019/6/28 15:51
	 */
	public void cacheIncrement(String key ,Integer value){
		stringRedisTemplate.opsForValue().increment(key,value);
	}

	/**
	 * 删除key
	 * @param key
	 * @return
	 */
	public Boolean delCacheWithKey(String key) {
		Boolean result = stringRedisTemplate.delete(key);
		return result;
	}
	
	/***
	 * 校验是否继续给该用户发送验证码
	 * @param mobile
	 * @param ip
	 * @return 1、验证码未失效   2、该手机用户验证码次数上限（3次上限）  3、该IP 请求验证码上限(5次上限) 0、继续发送
	 * @throws Exception  如果手机号是空的，或者是空字符串 空格都将抛出异常
	 */
	public int checkVerifyStatus(String mobile, String ip) throws Exception {
		if(StringUtils.isBlank(mobile)) {
			throw new Exception();
		}
		//获取到电话的验证码
		String valueWithKey = getValueWithKey(mobile);
		if (!StringUtils.isBlank(valueWithKey)){
			return 1;
		}else {
			String mobileCount = getValueWithKey("login_"+mobile);
			String ipCount = getValueWithKey("login_"+ip);
			if (StringUtils.isBlank(ipCount) || StringUtils.isBlank(mobileCount)) {
				//没有计数器
				return 0;
			}else if (Integer.parseInt(mobileCount) >= 3) {
				return 2;
			}else if(Integer.parseInt(ipCount) >= 5) {
				return 3;
			}
		}
		return 0;
	}


	
	 /** 
     * 获取用户真实IP地址，不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址, 
*  
     * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值，究竟哪个才是真正的用户端的真实IP呢？ 
     * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。 
     *  
     * 如：X-Forwarded-For：192.168.1.110, 192.168.1.120, 192.168.1.130, 
     * 192.168.1.100 
     *  
     * 用户真实IP为： 192.168.1.110 
     *  
     * @param request 
     * @return 
     */  
    public static String getIpAddress(HttpServletRequest request) {  
        String ip = request.getHeader("x-forwarded-for");  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("Proxy-Client-IP");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("WL-Proxy-Client-IP");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("HTTP_CLIENT_IP");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getRemoteAddr();  
        }  
        return ip;  
    }  
}
